
/* Application interface for PlayIt.

   by Rick Hudson, 1999

   This module provide higher level interface functions to PlayIt than
   playitv (which just provides the low level SWI veneers). Apps can ignore
   this and use only playitv but this can save some extra work.
*/


#ifndef _playit_c
#define _playit_c

#include "playitap.h"

#include <stdio.h>
#include <stdarg.h>
#include "kernel.h"

#define Xbit                      0x20000
#define OS_Module                 0x1E
#define OS_PlatformFeatures       0x6D
#define Wimp_StartTask            0x400DE

#define OSCLI(st) (playit_error*)_kernel_oscli(st)
#define SWI(swi,in,out) (playit_error*)_kernel_swi(swi,in,out)


static playit_error *MakeStaticError(char *fmt, ...)
{
   static playit_error serr;
   va_list ap;

   serr.errnum=0;
   va_start(ap, fmt);
   vsprintf(serr.errmess, fmt, ap);
   va_end(ap);
   return &serr;
}


/* Ensure that playit is loaded. If wimp is true then it also ensures that
   the wimp task is running. This must be called from a live wimp task if
   wimp is TRUE (not done if ver<1.59) */

playit_error *xplayit_ensure(int min_version, char *respath, int wimp,
              int *version)
{
  playit_error *err;
  char st[128];
  int ver;
  _kernel_swi_regs r;

  sprintf(st,"%sPlayIt %s", respath, respath);
  if (version) *version=0;
  ver=playit_read_version();    /* ver=0 if not loaded */
  if (version) *version=ver;
  if (ver) if (ver/100 != min_version/100)
     return MakeStaticError("Cannot load PlayIt %d.xx when %d.xx is already running", min_version/100, ver/100);
  if (ver<min_version) {
    playit_statusbits stat;
    if (ver) {   /* a version of PlayIt is already running. Is it idle? */
      if ((err=xplayit_status(&stat,NULL)) != NULL) return err;
      if (stat & PLAYIT_STAT_OPEN)
         return MakeStaticError("An version of PlayIt that is older than %d.%02d "
            "is running and cannot be shut down as it is busy", ver/100, ver%100);
    }
    r.r[0]=1;
    r.r[1]=(int)st;
    if ((err=SWI(OS_Module|Xbit, &r, &r)) != NULL) return err;
    if ((ver=playit_read_version()) == 0) return MakeStaticError("Could not load PlayIt");
    if (version) *version=ver;
    if (ver<min_version) return MakeStaticError("PlayIt %d.%02d or later is required (%d.%02d is available)",
       min_version/100, min_version%100, ver/100, ver%100);
  }
  if (xplayit_driver_info(NULL, NULL, NULL, NULL, NULL))
    if ((err=xplayit_load_driver(respath)) != NULL) return err;
  if (wimp && ver>=159) {
    r.r[0]=(int)"Desktop_PlayIt";
    if ((err=SWI(Wimp_StartTask|Xbit, &r, &r)) != NULL) return err;
  }
  return NULL;
}


/* alternative to xplayit_version that returns the verison as the
   result and zero if an error occurs (almost certainly because PlayIt isn't
   loaded.
*/

int playit_read_version(void)
{
  int ver;
  playit_error *err = xplayit_version(&ver);
  return err ? 0:ver;
}


/* single function to auto-play a file */

playit_error *xplayit_autoplay(const char *filename)
{
  playit_error *err;

  if ((err=xplayit_open_autodetect(filename)) == NULL)
    err=xplayit_play();
  return err;
}


const char *playit_file_type_name(int code)
{
  static const char *names[] = {
    "Unknown","Armadeus","Wave","Sun AU","AudioWorks","Psion A-law",
    "AIFF","Amiga IFF","Infocom","VOC"};
  if (code & 0xff0000) code=(code >> 16) & 0xff;   /* raw format union */
  if (code<1 || code>=PLAYIT_FILE_XXX) code=0;
  return names[code];
}


#endif
